
//***************************************************************************
//                             
//***************************************************************************

#ifndef _VHAND_SPHERE_TOPOLOGY_H
#define _VHAND_SPHERE_TOPOLOGY_H

//---------------------------------------------------------------------------
//  Includes
//---------------------------------------------------------------------------

#include <iostream>
#include <set>

#include <defESphereSystem.h>
#include <defESpring.h>
#include <defEGeometry.h>

#include "HandConfig.h"

namespace vhand
{

//---------------------------------------------------------------------------                                                 
// Forward Declaration
//--------------------------------------------------------------------------- 

using defE::XError;

using defE::IndexRange;
using defE::IndexRanges;

using defE::Sphere;
using defE::Spring;
using defE::SphereH;
using defE::SpringH;

using defE::Point3;
using defE::Vector4;
using defE::Matrix4;
using defE::Geometry;

//---------------------------------------------------------------------------                                                 
//  Public Types                                                                                                              
//--------------------------------------------------------------------------- 

typedef std::vector<unsigned int> SphereNeighbours;

typedef enum _AdjacencyType
{
    // for mapping spheres/bones to the right limbs
    MAP_SPHERE_BONES,
    MAP_SKIN_SPHERE,

    // for creating of springs
    SKIN_SKIN,
    SKIN_SPHERE,
    SPHERE_SPHERE,
    SPHERE_BONES

} AdjacencyType;

//***************************************************************************
//                             
//***************************************************************************

class Adjacency
{
public:
    Adjacency( unsigned int p0, unsigned int p1, AdjacencyType type );

    unsigned int getOut() const { return _p0; }
    unsigned int getIn() const { return _p1; }
    AdjacencyType getType() const { return _type; }


private:
    unsigned int _p0;
    unsigned int _p1;
    AdjacencyType _type;
};

std::ostream& operator<<( std::ostream &os, const Adjacency &adj );


//***************************************************************************
//                             
//***************************************************************************


/**
 */
class SphereTopology
{
public:

//---------------------------------------------------------------------------                                                 
//  Public Types                                                                                                              
//--------------------------------------------------------------------------- 

    static const float MTD = 0.000005; // the maximal tolerable derivation

//---------------------------------------------------------------------------                                                 
//  Public Functions
//--------------------------------------------------------------------------- 

    static std::set<unsigned int> intersection( const std::set<unsigned int> &set0, const std::set<unsigned int> &set1 );
    static bool isAdjacent( const Sphere &sp1, const Sphere &sp2, float threshold );
    static void findClosest( float *closestdist, unsigned int *closestindex, 
                             const Sphere &sp, const std::vector<Point3> *pnts );
    static void findClosest( float *closestdist, unsigned int *closestindex, 
                             const Point3 &pnt3, const std::vector<Sphere> *allsphere );

    void initHost( const Geometry *bones_geom,
                   const Geometry *skin_geom,
                   const std::vector<Sphere> *allsphere,
                   float threshold = 0.0 );

    const std::vector<Adjacency>* getAllAdjacency() const { return &_allAdjacency; }
    std::vector<Adjacency>* editAllAdjacency() { return &_allAdjacency; }

private:

    std::vector<Adjacency> _allAdjacency;

};

} // namespace vhand

#endif // _VHAND_SPHERE_TOPOLOGY_H

